package xcaptcha

import (
	"bytes"
	"encoding/base64"
	"errors"
	"gf-xb-api/utility/xconfig"

	"github.com/dchest/captcha"
	"github.com/go-redis/redis"
)

const (
	// DefaultMaxRedisKeys default max redis keys per expiration
	DefaultMaxRedisKeys = 500000

	// DefaultRedisPrefixKey default redis prefix key
	DefaultRedisPrefixKey = "Captcha"
)

var (
	store captcha.Store
	conf  *xconfig.CaptchaConfig
)

func init() {
	rc, err := xconfig.GetRedisConfig()
	if err != nil {
		panic(err)
	}

	conf, err = xconfig.GetCaptchaConfig()
	if err != nil {
		panic(err)
	}

	store, err = captcha.NewRedisStore(&redis.Options{Addr: rc.Host, DB: rc.Db, Password: rc.Password}, conf.Expiration, DefaultMaxRedisKeys, DefaultRedisPrefixKey)
	if err != nil {
		panic(err)
	}

	captcha.SetCustomStore(store)
}

// Set ... 存储验证码
func Set(id string, d []byte) {
	store.Set(id, d)
}

// Get ... 获得验证码
func Get(id string, clear bool) []byte {
	return store.Get(id, clear)
}

// generateCaptchaImage ... 生成验证码图片
func generateCaptchaImage(id string) (base64Str string, err error) {
	writer := bytes.Buffer{}
	err = captcha.WriteImage(&writer, id, conf.StdWith, conf.StdHeight)
	if err != nil {
		return "", errors.New("生成验证码图片失败")
	}

	bytes := writer.Bytes()
	base64Str = base64.StdEncoding.EncodeToString(bytes)
	return base64Str, nil
}

// New ... 新建验证码
func New() (id, code string, err error) {
	captchaId := captcha.NewLen(conf.Len)
	captchaCode, err := generateCaptchaImage(captchaId)
	if err != nil {
		return "", "", err
	}

	return captchaId, captchaCode, nil
}

// Reload ... 重载验证码
func Reload(id string) (newId, code string, err error) {

	// 重载验证码
	result := captcha.Reload(id)
	if !result {
		// 重载失败，需要新建一个验证码
		newId, code, err = New()
		return
	}

	// 重载成功，则返回验证码图片
	newId = id
	code, err = generateCaptchaImage(id)
	return
}

// Verify ... 验证验证码
func Verify(id, code string) bool {
	return captcha.VerifyString(id, code)
}
